﻿using System;
using System.Data;
using System.Configuration;
 
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

/// <summary>
///  
/// </summary>
public class ImageCompare
{
    public ImageCompare()
	{
		//
		// TODO: 在此处添加构造函数逻辑
		//
	}

	/// <summary>
	/// 比较两幅图片是否一致（使用Bitmap.GetPixel方式）
	/// </summary>
	/// <param name="bitmap1">图片1</param>
	/// <param name="bitmap2">图片2</param>
	/// <returns>如果两幅图片相同，返回0；如果图片1小于图片2，返回小于0的值；如果图片1大于图片2，返回大于0的值。</returns>
	public static int BitmapCompare(Bitmap bitmap1, Bitmap bitmap2)
	{
		int result = 0;	//假设两幅图片相同
		if (bitmap1 == null || bitmap2 == null)
			return -1;
		if (bitmap1.Width == bitmap2.Width && bitmap1.Height == bitmap2.Height)
		{
			for (int i = 0; i < bitmap1.Width; i++)
			{
				for (int j = 0; j < bitmap1.Height; j++)
				{
					Color color1 = bitmap1.GetPixel(i, j);
					Color color2 = bitmap2.GetPixel(i, j);
					if (color1 != color2)
					{
						result = color1.ToArgb() - color2.ToArgb();
						break;
					}
				}
				if (result != 0)
					break;
			}
		}
		else if (bitmap1.Width != bitmap2.Width)
		{
			result = bitmap1.Width - bitmap2.Width;
		}
		else if (bitmap1.Height != bitmap2.Height)
		{
			result = bitmap1.Height - bitmap2.Height;
		}
		return result;
	}

	/// <summary>
	/// 比较两幅图片是否一致（使用memcmp方式）
	/// </summary>
	/// <param name="bitmap1">图片1</param>
	/// <param name="bitmap2">图片2</param>
	/// <returns>如果两幅图片相同，返回0；如果图片1小于图片2，返回小于0的值；如果图片1大于图片2，返回大于0的值。</returns>
	public static int BitmapCompare2(Bitmap bitmap1, Bitmap bitmap2)
	{
		int result = 0;	//假设两幅图片相同
		if (bitmap1 == null || bitmap2 == null)
			return -1;
		if (bitmap1.Width == bitmap2.Width && bitmap1.Height == bitmap2.Height)
		{
			BitmapData bmd1 = bitmap1.LockBits(new Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat);
			BitmapData bmd2 = bitmap2.LockBits(new Rectangle(0, 0, bitmap2.Width, bitmap2.Height), ImageLockMode.ReadOnly, bitmap2.PixelFormat);
			int bytes = bmd1.Stride * bitmap1.Height;
			byte[] buff1 = new byte[bytes];
			byte[] buff2 = new byte[bytes];
			Marshal.Copy(bmd1.Scan0, buff1, 0, Marshal.SizeOf(typeof(byte)) * bytes);
			Marshal.Copy(bmd2.Scan0, buff2, 0, Marshal.SizeOf(typeof(byte)) * bytes);
			result = MemoryCompare(buff1, buff2);
			bitmap1.UnlockBits(bmd1);
			bitmap2.UnlockBits(bmd2);
		}
		else if (bitmap1.Width != bitmap2.Width)
		{
			result = bitmap1.Width - bitmap2.Width;
		}
		else if (bitmap1.Height != bitmap2.Height)
		{
			result = bitmap1.Height - bitmap2.Height;
		}
		return result;
	}

	/// <summary>
	/// 比较两幅图片是否一致（使用Marshal.ReadByte方式）
	/// </summary>
	/// <param name="bitmap1">图片1</param>
	/// <param name="bitmap2">图片2</param>
	/// <returns>如果两幅图片相同，返回0；如果图片1小于图片2，返回小于0的值；如果图片1大于图片2，返回大于0的值。</returns>
	public static int BitmapCompare3(Bitmap bitmap1, Bitmap bitmap2)
	{
		int result = 0;	//假设两幅图片相同
		if (bitmap1 == null || bitmap2 == null)
			return -1;
		if (bitmap1.Width == bitmap2.Width && bitmap1.Height == bitmap2.Height)
		{
			BitmapData bmd1 = bitmap1.LockBits(new Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat);
			BitmapData bmd2 = bitmap2.LockBits(new Rectangle(0, 0, bitmap2.Width, bitmap2.Height), ImageLockMode.ReadOnly, bitmap2.PixelFormat);
			IntPtr start1 = bmd1.Scan0;
			IntPtr start2 = bmd2.Scan0;
			int sizeOfByte = Marshal.SizeOf(typeof(byte));
			for (int i = 0; i < sizeOfByte * bmd1.Stride * bitmap1.Height; i++)
			{
				byte b1 = Marshal.ReadByte(start1, i);
				byte b2 = Marshal.ReadByte(start2, i);
				if (b1 != b2)
				{
					result = (int)(b1 - b2);
					break;
				}
			}
			bitmap1.UnlockBits(bmd1);
			bitmap2.UnlockBits(bmd2);
		}
		else if (bitmap1.Width != bitmap2.Width)
		{
			result = bitmap1.Width - bitmap2.Width;
		}
		else if (bitmap1.Height != bitmap2.Height)
		{
			result = bitmap1.Height - bitmap2.Height;
		}
		return result;
	}

	/// <summary>
	/// 比较两幅图片是否一致（使用自定义字节数组比较）
	/// </summary>
	/// <param name="bitmap1">图片1</param>
	/// <param name="bitmap2">图片2</param>
	/// <returns>如果两幅图片相同，返回0；如果图片1小于图片2，返回小于0的值；如果图片1大于图片2，返回大于0的值。</returns>
	public static int BitmapCompare4(Bitmap bitmap1, Bitmap bitmap2)
	{
		int result = 0;	//假设两幅图片相同
		if (bitmap1 == null || bitmap2 == null)
			return -1;
		if (bitmap1.Width == bitmap2.Width && bitmap1.Height == bitmap2.Height)
		{
			BitmapData bmd1 = bitmap1.LockBits(new Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat);
			BitmapData bmd2 = bitmap2.LockBits(new Rectangle(0, 0, bitmap2.Width, bitmap2.Height), ImageLockMode.ReadOnly, bitmap2.PixelFormat);
			int bytes = bmd1.Stride * bitmap1.Height;
			byte[] buff1 = new byte[bytes];
			byte[] buff2 = new byte[bytes];
			Marshal.Copy(bmd1.Scan0, buff1, 0, Marshal.SizeOf(typeof(byte)) * bytes);
			Marshal.Copy(bmd2.Scan0, buff2, 0, Marshal.SizeOf(typeof(byte)) * bytes);
			result = MemoryCompare2(buff1, buff2);
			bitmap1.UnlockBits(bmd1);
			bitmap2.UnlockBits(bmd2);
		}
		else if (bitmap1.Width != bitmap2.Width)
		{
			result = bitmap1.Width - bitmap2.Width;
		}
		else if (bitmap1.Height != bitmap2.Height)
		{
			result = bitmap1.Height - bitmap2.Height;
		}
		return result;
	}

	/// <summary>
	/// 用memcmp比较字节数组
	/// </summary>
	/// <param name="b1">字节数组1</param>
	/// <param name="b2">字节数组2</param>
	/// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>
	public static int MemoryCompare(byte[] b1, byte[] b2)
	{
		IntPtr retval = memcmp(b1, b2, new IntPtr(b1.Length));
		return retval.ToInt32();
	}

	/// <summary>
	/// 比较字节数组
	/// </summary>
	/// <param name="b1">字节数组1</param>
	/// <param name="b2">字节数组2</param>
	/// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>
	public static int MemoryCompare2(byte[] b1, byte[] b2)
	{
		int result = 0;
		if (b1.Length != b2.Length)
			result = b1.Length - b2.Length;
		else
		{
			for (int i = 0; i < b1.Length; i++)
			{
				if (b1[i] != b2[i])
				{
					result = (int)(b1[i] - b2[i]);
					break;
				}
			}
		}
		return result;
	}

	/// <summary>
	/// memcmp API
	/// </summary>
	/// <param name="b1">字节数组1</param>
	/// <param name="b2">字节数组2</param>
	/// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
	private static extern IntPtr memcmp(byte[] b1, byte[] b2, IntPtr count);
}
